home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 23 / CU Amiga - Super CD-ROM 23 (June 1998).iso / CUCD / Games / ADoomPPC / src / r_draw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-19  |  23.9 KB  |  1,095 lines

  1. // Emacs style mode select   -*- C++ -*- 
  2. //-----------------------------------------------------------------------------
  3. //
  4. // $Id:$
  5. //
  6. // Copyright (C) 1993-1996 by id Software, Inc.
  7. //
  8. // This source is available for distribution and/or modification
  9. // only under the terms of the DOOM Source Code License as
  10. // published by id Software. All rights reserved.
  11. //
  12. // The source is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
  15. // for more details.
  16. //
  17. // $Log:$
  18. //
  19. // DESCRIPTION:
  20. //    The actual span/column drawing functions.
  21. //    Here find the main potential for optimization,
  22. //     e.g. inline assembly, different algorithms.
  23. //
  24. //-----------------------------------------------------------------------------
  25.  
  26.  
  27. static const char
  28. rcsid[] = "$Id: r_draw.c,v 1.4 1997/02/03 16:47:55 b1 Exp $";
  29.  
  30.  
  31. #include "doomdef.h"
  32.  
  33. #include "i_system.h"
  34. #include "i_video.h"
  35. #include "z_zone.h"
  36. #include "w_wad.h"
  37.  
  38. #include "r_local.h"
  39.  
  40. // Needs access to LFB (guess what).
  41. #include "v_video.h"
  42.  
  43. // State.
  44. #include "doomstat.h"
  45.  
  46.  
  47. // ?
  48. //#define MAXWIDTH            1120
  49. //#define MAXHEIGHT            832
  50.  
  51. // status bar height at bottom of screen
  52. #define SBARHEIGHT        32
  53.  
  54. //
  55. // All drawing to the view buffer is accomplished in this file.
  56. // The other refresh files only know about ccordinates,
  57. //  not the architecture of the frame buffer.
  58. // Conveniently, the frame buffer is a linear one,
  59. //  and we need only the base address,
  60. //  and the total size == width*height*depth/8.,
  61. //
  62.  
  63.  
  64. byte*        viewimage; 
  65. int        viewwidth;
  66. int        scaledviewwidth;
  67. int        viewheight;
  68. int        viewwindowx;
  69. int        viewwindowy; 
  70. //byte*        ylookup[MAXHEIGHT]; 
  71. //byte*        ylookup2[MAXHEIGHT]; 
  72. //int        columnofs[MAXWIDTH]; 
  73. byte*        *ylookup; 
  74. byte*        *ylookup2;
  75. int        *columnofs;
  76.  
  77. // Color tables for different players,
  78. //  translate a limited part to another
  79. //  (color ramps used for  suit colors).
  80. //
  81. FAR byte    translations[3][256];    
  82.  
  83.  
  84.  
  85. //
  86. // Spectre/Invisibility.
  87. //
  88. #define FUZZTABLE       50
  89. #define FUZZOFF    (1)
  90.  
  91. int    fuzzoffset_init[FUZZTABLE] =
  92. {
  93.     FUZZOFF,-FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  94.     FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  95.     FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,
  96.     FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,
  97.     FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,
  98.     FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,
  99.     FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF,FUZZOFF,-FUZZOFF,FUZZOFF 
  100. };
  101.  
  102. int    *fuzzoffset;
  103. int    fuzzpos = 0; 
  104.  
  105. void init_r_draw (void);
  106.  
  107. void resinit_r_draw (void)
  108. {
  109.   int i;
  110.  
  111.   ylookup = (byte **)I_malloc (SCREENHEIGHT * sizeof(byte *));
  112.   ylookup2 = (byte **)I_malloc (SCREENHEIGHT * sizeof(byte *));
  113.   columnofs = (int *)I_malloc (SCREENWIDTH * sizeof(int));
  114.  
  115.   fuzzoffset = I_malloc ((SCREENHEIGHT + 50) * sizeof(int));
  116.   for (i = 0; i < SCREENHEIGHT + 50; i++)
  117.     fuzzoffset[i] = fuzzoffset_init[i % FUZZTABLE] * SCREENWIDTH;
  118.   fuzzpos=0;
  119.  
  120. //  init_r_draw ();
  121. }
  122.  
  123.  
  124. //
  125. // R_DrawColumn
  126. // Source is the top of the column to scale.
  127. //
  128. lighttable_t*        dc_colormap; 
  129. int            dc_x; 
  130. int            dc_yl; 
  131. int            dc_yh; 
  132. fixed_t            dc_iscale; 
  133. fixed_t            dc_texturemid;
  134.  
  135. // first pixel in a column (possibly virtual) 
  136. byte*            dc_source;        
  137.  
  138. // just for profiling 
  139. int            dccount;
  140.  
  141. //
  142. // A column is a vertical slice/span from a wall texture that,
  143. //  given the DOOM style restrictions on the view orientation,
  144. //  will always have constant z depth.
  145. // Thus a special case loop for very fast rendering can
  146. //  be used. It has also been used with Wolfenstein 3D.
  147. // 
  148. #ifndef UNROLL
  149. void R_DrawColumn (void) 
  150.     int            count; 
  151.     byte*        dest; 
  152.     fixed_t        frac;
  153.     fixed_t        fracstep;     
  154.  
  155.     count = dc_yh - dc_yl; 
  156.  
  157.     // Zero length, column does not exceed a pixel.
  158.     if (count < 0) 
  159.     return; 
  160.                  
  161. #ifdef RANGECHECK 
  162.     if ((unsigned)dc_x >= SCREENWIDTH
  163.     || dc_yl < 0
  164.     || dc_yh >= SCREENHEIGHT) 
  165.     I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); 
  166. #endif 
  167.  
  168.     // Framebuffer destination address.
  169.     // Use ylookup LUT to avoid multiply with ScreenWidth.
  170.     // Use columnofs LUT for subwindows? 
  171. //    dest = ylookup[dc_yl] + columnofs[dc_x];  
  172.     dest = ylookup2[dc_yl] + dc_x;
  173.  
  174.     // Determine scaling,
  175.     //  which is the only mapping to be done.
  176.     fracstep = dc_iscale; 
  177.     frac = dc_texturemid + (dc_yl-centery)*fracstep; 
  178.  
  179.     // Inner loop that does the actual texture mapping,
  180.     //  e.g. a DDA-line scaling.
  181.     // This is as fast as it gets.
  182.     do 
  183.     {
  184.     // Re-map color indices from wall texture column
  185.     //  using a lighting/special effects LUT.
  186.     *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
  187.     
  188.     dest += SCREENWIDTH; 
  189.     frac += fracstep;
  190.     
  191.     } while (count--); 
  192. #endif
  193.  
  194. // Loop unrolled.
  195. #ifdef UNROLL
  196. void R_DrawColumn (void) 
  197.     int            count;
  198.     byte*        source;
  199.     byte*        dest;
  200.     byte*        colormap;
  201.     
  202.     unsigned        frac;
  203.     unsigned        fracstep;
  204.     unsigned        fracstep2;
  205.     unsigned        fracstep3;
  206.     unsigned        fracstep4;     
  207.  
  208.     count = dc_yh - dc_yl + 1; 
  209.  
  210.     source = dc_source;
  211.     colormap = dc_colormap;
  212. //    dest = ylookup[dc_yl] + columnofs[dc_x];
  213.     dest = ylookup2[dc_yl] + dc_x;
  214.      
  215.     fracstep = dc_iscale<<9; 
  216.     frac = (dc_texturemid + (dc_yl-centery)*dc_iscale)<<9; 
  217.  
  218.     fracstep2 = fracstep+fracstep;
  219.     fracstep3 = fracstep2+fracstep;
  220.     fracstep4 = fracstep3+fracstep;
  221.     
  222.     while (count >= 8) 
  223.     { 
  224.     dest[0] = colormap[source[frac>>25]]; 
  225.     dest[SCREENWIDTH] = colormap[source[(frac+fracstep)>>25]]; 
  226.     dest[SCREENWIDTH*2] = colormap[source[(frac+fracstep2)>>25]]; 
  227.     dest[SCREENWIDTH*3] = colormap[source[(frac+fracstep3)>>25]];
  228.     
  229.     frac += fracstep4; 
  230.  
  231.     dest[SCREENWIDTH*4] = colormap[source[frac>>25]]; 
  232.     dest[SCREENWIDTH*5] = colormap[source[(frac+fracstep)>>25]]; 
  233.     dest[SCREENWIDTH*6] = colormap[source[(frac+fracstep2)>>25]]; 
  234.     dest[SCREENWIDTH*7] = colormap[source[(frac+fracstep3)>>25]]; 
  235.  
  236.     frac += fracstep4; 
  237.     dest += SCREENWIDTH*8; 
  238.     count -= 8;
  239.     } 
  240.     
  241.     while (count > 0)
  242.     { 
  243.     *dest = colormap[source[frac>>25]]; 
  244.     dest += SCREENWIDTH; 
  245.     frac += fracstep; 
  246.     count--;
  247.     } 
  248. }
  249. #endif
  250.  
  251.  
  252. void R_DrawColumnLow (void) 
  253.     int            count; 
  254.     byte*        dest; 
  255.     byte*        dest2;
  256.     fixed_t        frac;
  257.     fixed_t        fracstep;     
  258.  
  259.     count = dc_yh - dc_yl; 
  260.  
  261.     // Zero length.
  262.     if (count < 0) 
  263.     return; 
  264.                  
  265. #ifdef RANGECHECK 
  266.     if ((unsigned)dc_x >= SCREENWIDTH
  267.     || dc_yl < 0
  268.     || dc_yh >= SCREENHEIGHT)
  269.     {
  270.     
  271.     I_Error ("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x);
  272.     }
  273.     //    dccount++; 
  274. #endif 
  275.  
  276. //    dest = ylookup[dc_yl] + columnofs[dc_x<<1];
  277. //    dest2 = ylookup[dc_yl] + columnofs[(dc_x<<1)+1];
  278.     dest = ylookup2[dc_yl] + (dc_x<<1);
  279.     dest2 = ylookup2[dc_yl] + (dc_x<<1)+1;
  280.     
  281.     fracstep = dc_iscale; 
  282.     frac = dc_texturemid + (dc_yl-centery)*fracstep;
  283.     
  284.     do 
  285.     {
  286.     *dest2 = *dest = dc_colormap[dc_source[(frac>>FRACBITS)&127]];
  287.     dest += SCREENWIDTH;
  288.     dest2 += SCREENWIDTH;
  289.     frac += fracstep; 
  290.  
  291.     } while (count--);
  292. }
  293.  
  294.  
  295.  
  296. //
  297. // Framebuffer postprocessing.
  298. // Creates a fuzzy image by copying pixels
  299. //  from adjacent ones to left and right.
  300. // Used with an all black colormap, this
  301. //  could create the SHADOW effect,
  302. //  i.e. spectres and invisible players.
  303. //
  304. void R_DrawFuzzColumn (void) 
  305.     int            count; 
  306.     byte*        dest; 
  307.     fixed_t        frac;
  308.     fixed_t        fracstep;     
  309.  
  310.     // Adjust borders. Low... 
  311.     if (!dc_yl) 
  312.     dc_yl = 1;
  313.  
  314.     // .. and high.
  315.     if (dc_yh == viewheight-1) 
  316.     dc_yh = viewheight - 2; 
  317.          
  318.     count = dc_yh - dc_yl; 
  319.  
  320.     // Zero length.
  321.     if (count < 0) 
  322.     return; 
  323.  
  324.     
  325. #ifdef RANGECHECK 
  326.     if ((unsigned)dc_x >= SCREENWIDTH
  327.     || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
  328.     {
  329.     I_Error ("R_DrawFuzzColumn: %i to %i at %i",
  330.          dc_yl, dc_yh, dc_x);
  331.     }
  332. #endif
  333.  
  334.  
  335. //    dest = ylookup[dc_yl] + columnofs[dc_x];
  336.     dest = ylookup2[dc_yl] + dc_x;
  337.  
  338.     // Looks familiar.
  339.     fracstep = dc_iscale; 
  340.     frac = dc_texturemid + (dc_yl-centery)*fracstep; 
  341.  
  342.     // Looks like an attempt at dithering,
  343.     //  using the colormap #6 (of 0-31, a bit
  344.     //  brighter than average).
  345.     do 
  346.     {
  347.     // Lookup framebuffer, and retrieve
  348.     //  a pixel that is either one column
  349.     //  left or right of the current one.
  350.     // Add index from colormap to index.
  351.     *dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]]; 
  352.  
  353.     // Clamp table lookup index.
  354.     if (++fuzzpos == FUZZTABLE) 
  355.         fuzzpos = 0;
  356.     
  357.     dest += SCREENWIDTH;
  358.  
  359.     frac += fracstep; 
  360.     } while (count--); 
  361.  
  362.  
  363. //
  364. // Framebuffer postprocessing.
  365. // Creates a fuzzy image by copying pixels
  366. //  from adjacent ones to left and right.
  367. // Used with an all black colormap, this
  368. //  could create the SHADOW effect,
  369. //  i.e. spectres and invisible players.
  370. //
  371. void R_DrawFuzzColumnLow (void) 
  372.     int            count; 
  373.     byte*        dest; 
  374.     byte*        dest2; 
  375.     fixed_t        frac;
  376.     fixed_t        fracstep;     
  377.  
  378.     // Adjust borders. Low... 
  379.     if (!dc_yl) 
  380.     dc_yl = 1;
  381.  
  382.     // .. and high.
  383.     if (dc_yh == viewheight-1) 
  384.     dc_yh = viewheight - 2; 
  385.          
  386.     count = dc_yh - dc_yl; 
  387.  
  388.     // Zero length.
  389.     if (count < 0) 
  390.     return; 
  391.  
  392.     
  393. #ifdef RANGECHECK 
  394.     if (((unsigned)dc_x << 1) >= SCREENWIDTH
  395.     || dc_yl < 0 || dc_yh >= SCREENHEIGHT)
  396.     {
  397.     I_Error ("R_DrawFuzzColumn: %i to %i at %i",
  398.          dc_yl, dc_yh, dc_x);
  399.     }
  400. #endif
  401.  
  402. //    dest = ylookup[dc_yl] + columnofs[dc_x << 1];
  403. //    dest2 = ylookup[dc_yl] + columnofs[(dc_x << 1) + 1];
  404.     dest = ylookup2[dc_yl] + (dc_x<<1);
  405.     dest2 = ylookup2[dc_yl] + (dc_x<<1)+1;
  406.  
  407.     // Looks familiar.
  408.     fracstep = dc_iscale;
  409.     frac = dc_texturemid + (dc_yl-centery)*fracstep;
  410.  
  411.     // Looks like an attempt at dithering,
  412.     //  using the colormap #6 (of 0-31, a bit
  413.     //  brighter than average).
  414.     do 
  415.     {
  416.     // Lookup framebuffer, and retrieve
  417.     //  a pixel that is either one column
  418.     //  left or right of the current one.
  419.     // Add index from colormap to index.
  420.     *dest2 = *dest = colormaps[6*256+dest[fuzzoffset[fuzzpos]]];
  421.  
  422.     // Clamp table lookup index.
  423.     if (++fuzzpos == FUZZTABLE)
  424.         fuzzpos = 0;
  425.  
  426.     dest += SCREENWIDTH;
  427.     dest2 += SCREENWIDTH;
  428.  
  429.     frac += fracstep;
  430.     } while (count--);
  431. }
  432.  
  433.   
  434.  
  435.  
  436. //
  437. // R_DrawTranslatedColumn
  438. // Used to draw player sprites
  439. //  with the green colorramp mapped to others.
  440. // Could be used with different translation
  441. //  tables, e.g. the lighter colored version
  442. //  of the BaronOfHell, the HellKnight, uses
  443. //  identical sprites, kinda brightened up.
  444. //
  445. byte*    dc_translation;
  446. byte*    translationtables;
  447.  
  448. void R_DrawTranslatedColumn (void) 
  449.     int            count; 
  450.     byte*        dest; 
  451.     fixed_t        frac;
  452.     fixed_t        fracstep;     
  453.  
  454.     count = dc_yh - dc_yl; 
  455.     if (count < 0) 
  456.     return; 
  457.                  
  458. #ifdef RANGECHECK 
  459.     if ((unsigned)dc_x >= SCREENWIDTH
  460.     || dc_yl < 0
  461.     || dc_yh >= SCREENHEIGHT)
  462.     {
  463.     I_Error ( "R_DrawColumn: %i to %i at %i",
  464.           dc_yl, dc_yh, dc_x);
  465.     }
  466.     
  467. #endif 
  468.  
  469.  
  470. //    dest = ylookup[dc_yl] + columnofs[dc_x]; 
  471.     dest = ylookup2[dc_yl] + dc_x;
  472.  
  473.     // Looks familiar.
  474.     fracstep = dc_iscale; 
  475.     frac = dc_texturemid + (dc_yl-centery)*fracstep; 
  476.  
  477.     // Here we do an additional index re-mapping.
  478.     do 
  479.     {
  480.     // Translation tables are used
  481.     //  to map certain colorramps to other ones,
  482.     //  used with PLAY sprites.
  483.     // Thus the "green" ramp of the player 0 sprite
  484.     //  is mapped to gray, red, black/indigo. 
  485.     *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
  486.     dest += SCREENWIDTH;
  487.     
  488.     frac += fracstep; 
  489.     } while (count--); 
  490.  
  491.  
  492.  
  493.  
  494. //
  495. // R_DrawTranslatedColumn
  496. // Used to draw player sprites
  497. //  with the green colorramp mapped to others.
  498. // Could be used with different translation
  499. //  tables, e.g. the lighter colored version
  500. //  of the BaronOfHell, the HellKnight, uses
  501. //  identical sprites, kinda brightened up.
  502. //
  503. //byte*    dc_translation;
  504. //byte*    translationtables;
  505.  
  506. void R_DrawTranslatedColumnLow (void) 
  507.     int            count; 
  508.     byte*        dest; 
  509.     byte*        dest2;
  510.     fixed_t        frac;
  511.     fixed_t        fracstep;     
  512.  
  513.     count = dc_yh - dc_yl; 
  514.     if (count < 0) 
  515.     return; 
  516.                  
  517. #ifdef RANGECHECK 
  518.     if (((unsigned)dc_x << 1) >= SCREENWIDTH
  519.     || dc_yl < 0
  520.     || dc_yh >= SCREENHEIGHT)
  521.     {
  522.     I_Error ( "R_DrawColumn: %i to %i at %i",
  523.           dc_yl, dc_yh, dc_x);
  524.     }
  525.     
  526. #endif 
  527.  
  528. //    dest = ylookup[dc_yl] + columnofs[dc_x << 1]; 
  529. //    dest2 = ylookup[dc_yl] + columnofs[(dc_x << 1) + 1];
  530.     dest = ylookup2[dc_yl] + (dc_x<<1);
  531.     dest2 = ylookup2[dc_yl] + (dc_x<<1)+1;
  532.  
  533.     // Looks familiar.
  534.     fracstep = dc_iscale; 
  535.     frac = dc_texturemid + (dc_yl-centery)*fracstep; 
  536.  
  537.     // Here we do an additional index re-mapping.
  538.     do 
  539.     {
  540.     // Translation tables are used
  541.     //  to map certain colorramps to other ones,
  542.     //  used with PLAY sprites.
  543.     // Thus the "green" ramp of the player 0 sprite
  544.     //  is mapped to gray, red, black/indigo. 
  545.     *dest2 = *dest = dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]];
  546.     dest += SCREENWIDTH;
  547.     dest2 += SCREENWIDTH;
  548.     
  549.     frac += fracstep; 
  550.     } while (count--); 
  551.  
  552.  
  553.  
  554.  
  555. //
  556. // R_InitTranslationTables
  557. // Creates the translation tables to map
  558. //  the green color ramp to gray, brown, red.
  559. // Assumes a given structure of the PLAYPAL.
  560. // Could be read from a lump instead.
  561. //
  562. void R_InitTranslationTables (void)
  563. {
  564.     int        i;
  565.     
  566.     translationtables = Z_Malloc (256*3+255, PU_STATIC, 0);
  567.     translationtables = (byte *)(( (int)translationtables + 255 )& ~255);
  568.     
  569.     // translate just the 16 green colors
  570.     for (i=0 ; i<256 ; i++)
  571.     {
  572.     if (i >= 0x70 && i<= 0x7f)
  573.     {
  574.         // map green ramp to gray, brown, red
  575.         translationtables[i] = 0x60 + (i&0xf);
  576.         translationtables [i+256] = 0x40 + (i&0xf);
  577.         translationtables [i+512] = 0x20 + (i&0xf);
  578.     }
  579.     else
  580.     {
  581.         // Keep all other colors as is.
  582.         translationtables[i] = translationtables[i+256] 
  583.         = translationtables[i+512] = i;
  584.     }
  585.     }
  586. }
  587.  
  588.  
  589.  
  590.  
  591. //
  592. // R_DrawSpan 
  593. // With DOOM style restrictions on view orientation,
  594. //  the floors and ceilings consist of horizontal slices
  595. //  or spans with constant z depth.
  596. // However, rotation around the world z axis is possible,
  597. //  thus this mapping, while simpler and faster than
  598. //  perspective correct texture mapping, has to traverse
  599. //  the texture at an angle in all but a few cases.
  600. // In consequence, flats are not stored by column (like walls),
  601. //  and the inner loop has to step in texture space u and v.
  602. //
  603. int            ds_y; 
  604. int            ds_x1; 
  605. int            ds_x2;
  606.  
  607. lighttable_t*        ds_colormap; 
  608.  
  609. fixed_t            ds_xfrac; 
  610. fixed_t            ds_yfrac; 
  611. fixed_t            ds_xstep; 
  612. fixed_t            ds_ystep;
  613.  
  614. // start of a 64*64 tile image 
  615. byte*            ds_source;    
  616.  
  617. // just for profiling
  618. int            dscount;
  619.  
  620.  
  621. //
  622. // Draws the actual span.
  623. #ifndef UNROLL
  624. void R_DrawSpan (void) 
  625.     fixed_t        xfrac;
  626.     fixed_t        yfrac; 
  627.     byte*        dest; 
  628.     int            count;
  629.     int            spot; 
  630.      
  631. #ifdef RANGECHECK 
  632.     if (ds_x2 < ds_x1
  633.     || ds_x1<0
  634.     || ds_x2>=SCREENWIDTH  
  635.     || (unsigned)ds_y>SCREENHEIGHT)
  636.     {
  637.     I_Error( "R_DrawSpan: %i to %i at %i",
  638.          ds_x1,ds_x2,ds_y);
  639.     }
  640. //    dscount++; 
  641. #endif 
  642.  
  643.     
  644.     xfrac = ds_xfrac; 
  645.     yfrac = ds_yfrac; 
  646.      
  647. //    dest = ylookup[ds_y] + columnofs[ds_x1];
  648.     dest = ylookup2[ds_y] + ds_x1;
  649.  
  650.     // We do not check for zero spans here?
  651.     count = ds_x2 - ds_x1; 
  652.  
  653.     do 
  654.     {
  655.     // Current texture index in u,v.
  656.     spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
  657.  
  658.     // Lookup pixel from flat texture tile,
  659.     //  re-index using light/colormap.
  660.     *dest++ = ds_colormap[ds_source[spot]];
  661.  
  662.     // Next step in u,v.
  663.     xfrac += ds_xstep; 
  664.     yfrac += ds_ystep;
  665.     
  666.     } while (count--); 
  667. #endif
  668.  
  669. // Loop unrolled by 4.
  670. #ifdef UNROLL
  671. void R_DrawSpan (void) 
  672.     unsigned    position, step;
  673.  
  674.     byte*    source;
  675.     byte*    colormap;
  676.     byte*    dest;
  677.     
  678.     unsigned    count;
  679.     unsigned    spot; 
  680.     unsigned    value;
  681.     unsigned    temp;
  682.     unsigned    xtemp;
  683.     unsigned    ytemp;
  684.         
  685.     position = ((ds_xfrac<<10)&0xffff0000) | ((ds_yfrac>>6)&0xffff);
  686.     step = ((ds_xstep<<10)&0xffff0000) | ((ds_ystep>>6)&0xffff);
  687.         
  688.     source = ds_source;
  689.     colormap = ds_colormap;
  690. //    dest = ylookup[ds_y] + columnofs[ds_x1];     
  691.     dest = ylookup2[ds_y] + ds_x1;
  692.     count = ds_x2 - ds_x1 + 1; 
  693.     
  694.     while (count >= 4) 
  695.     { 
  696.     ytemp = position>>4;
  697.     ytemp = ytemp & 4032;
  698.     xtemp = position>>26;
  699.     spot = xtemp | ytemp;
  700.     position += step;
  701.     dest[0] = colormap[source[spot]]; 
  702.  
  703.     ytemp = position>>4;
  704.     ytemp = ytemp & 4032;
  705.     xtemp = position>>26;
  706.     spot = xtemp | ytemp;
  707.     position += step;
  708.     dest[1] = colormap[source[spot]];
  709.     
  710.     ytemp = position>>4;
  711.     ytemp = ytemp & 4032;
  712.     xtemp = position>>26;
  713.     spot = xtemp | ytemp;
  714.     position += step;
  715.     dest[2] = colormap[source[spot]];
  716.     
  717.     ytemp = position>>4;
  718.     ytemp = ytemp & 4032;
  719.     xtemp = position>>26;
  720.     spot = xtemp | ytemp;
  721.     position += step;
  722.     dest[3] = colormap[source[spot]]; 
  723.         
  724.     count -= 4;
  725.     dest += 4;
  726.     } 
  727.     while (count > 0) 
  728.     { 
  729.     ytemp = position>>4;
  730.     ytemp = ytemp & 4032;
  731.     xtemp = position>>26;
  732.     spot = xtemp | ytemp;
  733.     position += step;
  734.     *dest++ = colormap[source[spot]]; 
  735.     count--;
  736.     } 
  737. #endif
  738.  
  739.  
  740. //
  741. // Again..
  742. //
  743. void R_DrawSpanLow (void) 
  744.     fixed_t        xfrac;
  745.     fixed_t        yfrac; 
  746.     byte*        dest; 
  747.     int            count;
  748.     int            spot; 
  749.      
  750. #ifdef RANGECHECK 
  751.     if (ds_x2 < ds_x1
  752.     || ds_x1<0
  753.     || ds_x2>=SCREENWIDTH  
  754.     || (unsigned)ds_y>SCREENHEIGHT)
  755.     {
  756.     I_Error( "R_DrawSpan: %i to %i at %i",
  757.          ds_x1,ds_x2,ds_y);
  758.     }
  759. //    dscount++; 
  760. #endif 
  761.      
  762.     xfrac = ds_xfrac; 
  763.     yfrac = ds_yfrac; 
  764.  
  765. //    dest = ylookup[ds_y] + columnofs[ds_x1<<1];
  766.     dest = ylookup2[ds_y] + (ds_x1<<1);
  767.   
  768.     count = ds_x2 - ds_x1; 
  769.     do 
  770.     { 
  771.     spot = ((yfrac>>(16-6))&(63*64)) + ((xfrac>>16)&63);
  772.     // Lowres/blocky mode does it twice,
  773.     //  while scale is adjusted appropriately.
  774.     *dest++ = ds_colormap[ds_source[spot]]; 
  775.     *dest++ = ds_colormap[ds_source[spot]];
  776.     
  777.     xfrac += ds_xstep; 
  778.     yfrac += ds_ystep; 
  779.  
  780.     } while (count--); 
  781. }
  782.  
  783.  
  784. //
  785. // R_InitBuffer 
  786. // Creates lookup tables that avoid
  787. //  multiplies and other hazzles
  788. //  for getting the framebuffer address
  789. //  of a pixel to draw.
  790. //
  791. void
  792. R_InitBuffer
  793. ( int        width,
  794.   int        height ) 
  795.     int        i, offset;
  796.  
  797.     // Handle resize,
  798.     //  e.g. smaller view windows
  799.     //  with border and/or status bar.
  800.     viewwindowx = (SCREENWIDTH-width) >> 1; 
  801.  
  802.     // Column offset. For windows.
  803.     for (i=0 ; i<width ; i++) 
  804.     columnofs[i] = viewwindowx + i;
  805.  
  806.     // Samw with base row offset.
  807.     if (width == SCREENWIDTH) 
  808.     viewwindowy = 0; 
  809.     else 
  810.     viewwindowy = (SCREENHEIGHT-SBARHEIGHT-height) >> 1; 
  811.  
  812.     // Preclaculate all row offsets.
  813.     offset = viewwindowy * SCREENWIDTH;
  814.     for (i=0 ; i<height ; i++) {
  815.     ylookup[i] = screens[0] + offset;
  816.         ylookup2[i] = ylookup[i] + viewwindowx;
  817.         offset += SCREENWIDTH;
  818.     }
  819.  
  820.  
  821.  
  822.  
  823. //
  824. // R_FillBackScreen
  825. // Fills the back screen with a pattern
  826. //  for variable screen sizes
  827. // Also draws a beveled edge.
  828. //
  829. void R_FillBackScreen (void) 
  830.     byte*    src;
  831.     byte*    dest; 
  832.     int        x;
  833.     int        y; 
  834.     patch_t*    patch;
  835.  
  836.     // DOOM border patch.
  837.     char    name1[] = "FLOOR7_2";
  838.  
  839.     // DOOM II border patch.
  840.     char    name2[] = "GRNROCK";    
  841.  
  842.     char*    name;
  843.     
  844.     if ((scaledviewwidth == SCREENWIDTH)&&(viewheight==SCREENHEIGHT))
  845.     return;
  846.     
  847.     if ( gamemode == commercial)
  848.     name = name2;
  849.     else
  850.     name = name1;
  851.     
  852.     src = W_CacheLumpName (name, PU_CACHE); 
  853.     dest = screens[1]; 
  854.      
  855.     for (y=0 ; y<SCREENHEIGHT/*-SBARHEIGHT*/ ; y++)
  856.     { 
  857.     for (x=0 ; x<SCREENWIDTH/64 ; x++) 
  858.     { 
  859.         memcpy (dest, src+((y&63)<<6), 64); 
  860.         dest += 64; 
  861.     } 
  862.  
  863.     if (SCREENWIDTH&63) 
  864.     { 
  865.         memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63); 
  866.         dest += (SCREENWIDTH&63); 
  867.     } 
  868.     } 
  869.     if (SCREENWIDTH==scaledviewwidth)
  870.      return;
  871.  
  872.    if ((viewwindowy-8)>=0)
  873.      {
  874.      patch = W_CacheLumpName ("brdr_t",PU_CACHE);
  875.      for (x=0 ; x<scaledviewwidth ; x+=8)
  876.        V_DrawPatch (viewwindowx+x,viewwindowy-8,1,patch);
  877.      }
  878.    if ((viewwindowy+viewheight+8)<(SCREENHEIGHT-SBARHEIGHT))
  879.      {
  880.      patch = W_CacheLumpName ("brdr_b",PU_CACHE);
  881.      for (x=0 ; x<scaledviewwidth ; x+=8)
  882.        V_DrawPatch (viewwindowx+x,viewwindowy+viewheight,1,patch);
  883.      }
  884.    if ((viewwindowx-8)>=0)
  885.      {
  886.      patch = W_CacheLumpName ("brdr_l",PU_CACHE);
  887.      for (y=0 ; y<viewheight ; y+=8)
  888.        V_DrawPatch (viewwindowx-8,viewwindowy+y,1,patch);
  889.      }
  890.    if ((viewwindowx+scaledviewwidth+8)<SCREENWIDTH)
  891.      {
  892.      patch = W_CacheLumpName ("brdr_r",PU_CACHE);
  893.      for (y=0 ; y<viewheight ; y+=8)
  894.        V_DrawPatch (viewwindowx+scaledviewwidth,viewwindowy+y,1,patch);
  895.      }
  896.  
  897.     // Draw beveled edge.
  898.     if (((viewwindowx-8)>=0)&&((viewwindowy-8)>=0))
  899.       V_DrawPatch (viewwindowx-8,
  900.          viewwindowy-8,
  901.          1,
  902.          W_CacheLumpName ("brdr_tl",PU_CACHE));
  903.     
  904.     if (((viewwindowx+scaledviewwidth+8)<SCREENWIDTH)&&((viewwindowy-8)>=0))
  905.       V_DrawPatch (viewwindowx+scaledviewwidth,
  906.          viewwindowy-8,
  907.          1,
  908.          W_CacheLumpName ("brdr_tr",PU_CACHE));
  909.  
  910.     if (((viewwindowx-8)>=0)&&((viewwindowy+viewheight+8)<(SCREENHEIGHT-SBARHEIGHT)))
  911.       V_DrawPatch (viewwindowx-8,
  912.          viewwindowy+viewheight,
  913.          1,
  914.          W_CacheLumpName ("brdr_bl",PU_CACHE));
  915.     
  916.     if (((viewwindowx+scaledviewwidth+8)<SCREENWIDTH)&&((viewwindowy+viewheight+8)<(SCREENHEIGHT-SBARHEIGHT)))
  917.       V_DrawPatch (viewwindowx+scaledviewwidth,
  918.          viewwindowy+viewheight,
  919.          1,
  920.          W_CacheLumpName ("brdr_br",PU_CACHE));
  921.  
  922.  
  923. #if 0
  924.  
  925.     if (scaledviewwidth == 320)
  926.     return;
  927.     
  928.     if ( gamemode == commercial)
  929.     name = name2;
  930.     else
  931.     name = name1;
  932.     
  933.     src = W_CacheLumpName (name, PU_CACHE); 
  934.     dest = screens[1]; 
  935.      
  936.     for (y=0 ; y<SCREENHEIGHT-SBARHEIGHT ; y++) 
  937.     { 
  938.     for (x=0 ; x<SCREENWIDTH/64 ; x++) 
  939.     { 
  940.         memcpy (dest, src+((y&63)<<6), 64); 
  941.         dest += 64; 
  942.     } 
  943.  
  944.     if (SCREENWIDTH&63) 
  945.     { 
  946.         memcpy (dest, src+((y&63)<<6), SCREENWIDTH&63); 
  947.         dest += (SCREENWIDTH&63); 
  948.     } 
  949.     } 
  950.     
  951.     patch = W_CacheLumpName ("brdr_t",PU_CACHE);
  952.  
  953.     for (x=0 ; x<scaledviewwidth ; x+=8)
  954.     V_DrawPatch (viewwindowx+x,viewwindowy-8,1,patch);
  955.     patch = W_CacheLumpName ("brdr_b",PU_CACHE);
  956.  
  957.     for (x=0 ; x<scaledviewwidth ; x+=8)
  958.     V_DrawPatch (viewwindowx+x,viewwindowy+viewheight,1,patch);
  959.     patch = W_CacheLumpName ("brdr_l",PU_CACHE);
  960.  
  961.     for (y=0 ; y<viewheight ; y+=8)
  962.     V_DrawPatch (viewwindowx-8,viewwindowy+y,1,patch);
  963.     patch = W_CacheLumpName ("brdr_r",PU_CACHE);
  964.  
  965.     for (y=0 ; y<viewheight ; y+=8)
  966.     V_DrawPatch (viewwindowx+scaledviewwidth,viewwindowy+y,1,patch);
  967.  
  968.  
  969.     // Draw beveled edge. 
  970.     V_DrawPatch (viewwindowx-8,
  971.          viewwindowy-8,
  972.          1,
  973.          W_CacheLumpName ("brdr_tl",PU_CACHE));
  974.     
  975.     V_DrawPatch (viewwindowx+scaledviewwidth,
  976.          viewwindowy-8,
  977.          1,
  978.          W_CacheLumpName ("brdr_tr",PU_CACHE));
  979.     
  980.     V_DrawPatch (viewwindowx-8,
  981.          viewwindowy+viewheight,
  982.          1,
  983.          W_CacheLumpName ("brdr_bl",PU_CACHE));
  984.     
  985.     V_DrawPatch (viewwindowx+scaledviewwidth,
  986.          viewwindowy+viewheight,
  987.          1,
  988.          W_CacheLumpName ("brdr_br",PU_CACHE));
  989.  
  990. #endif
  991.  
  992.  
  993.  
  994. //
  995. // Copy a screen buffer.
  996. //
  997. void
  998. R_VideoErase
  999. ( unsigned    ofs,
  1000.   int        count ) 
  1001.   // LFB copy.
  1002.   // This might not be a good idea if memcpy
  1003.   //  is not optiomal, e.g. byte by byte on
  1004.   //  a 32bit CPU, as GNU GCC/Linux libc did
  1005.   //  at one point.
  1006.     memcpy (screens[0]+ofs, screens[1]+ofs, count); 
  1007.  
  1008.  
  1009. //
  1010. // R_DrawViewBorder
  1011. // Draws the border around the view
  1012. //  for different size windows?
  1013. //
  1014. //void
  1015. //V_MarkRect
  1016. //( int        x,
  1017. //  int        y,
  1018. //  int        width,
  1019. //  int        height ); 
  1020.  
  1021. void R_DrawViewBorder (void) 
  1022.     int        top;
  1023.     int        side,side2;
  1024.     int        ofs;
  1025.     int        i; 
  1026.  
  1027.     //if screenwidth>320, draw stuff around status bar, even if scaledviewwidth==SCREENWIDTH
  1028.     if ((SCREENWIDTH>320)&&(SCREENHEIGHT!=viewheight))
  1029.       {
  1030.       ofs=(SCREENHEIGHT-SBARHEIGHT)*SCREENWIDTH;
  1031.       side=(SCREENWIDTH-320)/2; side2=side*2;
  1032.       R_VideoErase(ofs,side);
  1033.  
  1034.       ofs+=(SCREENWIDTH-side);
  1035.       for (i=1;i<SBARHEIGHT;i++)
  1036.         {
  1037.         R_VideoErase(ofs,side2);
  1038.         ofs+=SCREENWIDTH;
  1039.         }
  1040.       R_VideoErase(ofs,side);
  1041.       }
  1042.  
  1043. //    if (scaledviewwidth == SCREENWIDTH) 
  1044.     if (viewheight>=(SCREENHEIGHT-SBARHEIGHT))
  1045.     return; 
  1046.   
  1047.     top = ((SCREENHEIGHT-SBARHEIGHT)-viewheight)/2; 
  1048.     side = (SCREENWIDTH-scaledviewwidth)/2; 
  1049.  
  1050.     // copy top and one line of left side 
  1051.     R_VideoErase (0, top*SCREENWIDTH+side); 
  1052.  
  1053.     // copy one line of right side and bottom 
  1054.     ofs = (viewheight+top)*SCREENWIDTH-side; 
  1055.     R_VideoErase (ofs, top*SCREENWIDTH+side); 
  1056.  
  1057.     // copy sides using wraparound 
  1058.     ofs = top*SCREENWIDTH + SCREENWIDTH-side; 
  1059.     side <<= 1;
  1060.     
  1061.     for (i=1 ; i<viewheight ; i++) 
  1062.     { 
  1063.     R_VideoErase (ofs, side); 
  1064.     ofs += SCREENWIDTH; 
  1065.     } 
  1066.  
  1067.     // ? 
  1068.     I_MarkRect (0,0,SCREENWIDTH, SCREENHEIGHT-SBARHEIGHT); 
  1069.  
  1070.  
  1071.